// Copyright (C) 1953-2022 NUDT
// Verilog module name - cycle_start_judge 
// Version: V3.4.0.20220420
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
///////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ps
module cycle_start_generate(
input                 i_clk,
input                 i_rst_n,
(*MARK_DEBUG="true"*)input                 i_syn_ok,
(*MARK_DEBUG="true"*)input                 i_cycle_start_enable,
(*MARK_DEBUG="true"*)input                 i_base_time_wr,
(*MARK_DEBUG="true"*)input     [31:0]      iv_cycle_length, 
(*MARK_DEBUG="true"*)input     [79:0]      iv_base_time, 
(*MARK_DEBUG="true"*)input     [79:0]      iv_syn_clk,              
(*MARK_DEBUG="true"*)output    reg         o_cycle_start
);         
 
(*MARK_DEBUG="true"*) reg       [79:0]      rv_cycle_start_time;
(*MARK_DEBUG="true"*) reg       [1:0]       pcj_state;
(*MARK_DEBUG="true"*) wire                  w_ok_and_enable;
assign w_ok_and_enable =  i_syn_ok & i_cycle_start_enable;

localparam            IDLE_S                   = 2'd0,
                      SET_CYCLE_STATE_TIME_S   = 2'd1,
                      START_CYCLE_S            = 2'd2;

always@(posedge i_clk or negedge i_rst_n)begin 
    if(!i_rst_n) begin
		 o_cycle_start          <=1'd0;
         rv_cycle_start_time    <=80'd0;
         pcj_state              <=IDLE_S;
    end
    else begin
        case(pcj_state)
        IDLE_S:begin           
            if(w_ok_and_enable ==1'b0)begin          
                o_cycle_start  <=1'd0;                
                pcj_state      <=IDLE_S;
            end
            else begin
                if((w_ok_and_enable==1'd1)&&(i_base_time_wr==1'd1)&&(iv_cycle_length>32'd0))begin
                    rv_cycle_start_time    <= iv_base_time;	
                    o_cycle_start          <=1'd0;
                    pcj_state              <=SET_CYCLE_STATE_TIME_S;
                end 
                else begin
                    rv_cycle_start_time    <=80'd0;
                    o_cycle_start          <=1'd0;
                    pcj_state              <=IDLE_S;
                end	          					
            end
        end
        SET_CYCLE_STATE_TIME_S:begin 
            o_cycle_start<=1'b0;			
            if(rv_cycle_start_time <=iv_syn_clk)begin                  		
                if(rv_cycle_start_time[31:0]+iv_cycle_length>32'd1000000000)begin
                    rv_cycle_start_time[79:32]<=rv_cycle_start_time[79:32]+1'b1;
                    rv_cycle_start_time[31:0] <=rv_cycle_start_time[31:0]+iv_cycle_length-32'd1000000000;
                end
                else begin
                    rv_cycle_start_time[79:32]<=rv_cycle_start_time[79:32];
                    rv_cycle_start_time[31:0] <=rv_cycle_start_time[31:0]+iv_cycle_length;
                end             
                if (w_ok_and_enable==1'd1)begin
                    pcj_state<=START_CYCLE_S; 
                end
                else begin
                    pcj_state<=IDLE_S;
                end            
            end
            else begin
                rv_cycle_start_time <= rv_cycle_start_time;
                if (w_ok_and_enable==1'd1)begin
                    pcj_state<=SET_CYCLE_STATE_TIME_S; 
                end
                else begin
                    pcj_state<=IDLE_S;
                end                   
            end   
        end
        START_CYCLE_S:begin
			o_cycle_start<=1'b1;  
			pcj_state <= SET_CYCLE_STATE_TIME_S;
        end
        default:begin
			o_cycle_start     <= 1'h0;
            rv_cycle_start_time       <=80'd0;
			pcj_state                 <=IDLE_S;	
		end  
        endcase           
    end       
end
endmodule